﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LCA.Community.DAL.Interfaces;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using LCA.Community.DAL.Model;

namespace LCA.Community.DAL
{
    /// <summary>
    /// The base repository to manage general data.
    /// </summary>
    /// <typeparam name="T">The class that represents the table data.</typeparam>
    public class BaseRepository<T> : IBaseRepository<T> where T : BasicDataModel
    {
        /// <summary>
        /// The context to access to the data.
        /// </summary>
        private IDataServiceContext<T> _context;

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseRepository&lt;T&gt;"/> class.
        /// </summary>
        public BaseRepository(IDataServiceContext<T> dataServiceContext)
        {
            _context = dataServiceContext;
        }

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void Add(T entity)
        {
            _context.AddObject(_context.TableName, entity);
            _context.SaveChanges();
        }

        /// <summary>
        /// Gets the specified entity by the ID.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public virtual T Get(string id)
        {
            return (from entity in _context.TableEntities
                    where entity.RowKey == id
                    select entity).FirstOrDefault();
        }

        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void Delete(T entity)
        {
            _context.TryAttachTo(entity);
            _context.DeleteObject(entity);
            _context.SaveChanges();
        }

        /// <summary>
        /// Deletes the test entities.
        /// </summary>
        public virtual void DeleteTestEntities()
        {
            Entities.Where(entity => entity.RowKey.StartsWith("test")).ToList().ForEach(entity => Delete(entity));
        }

        /// <summary>
        /// Deletes the specified entity by the id.
        /// </summary>
        /// <param name="id">The id.</param>
        public virtual void Delete(string id)
        {
            var entity = Get(id);
            Delete(entity);
        }

        /// <summary>
        /// Updates the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void Update(T entity)
        {
            _context.TryAttachTo(entity);
            _context.UpdateObject(entity);
            _context.SaveChanges();
        }

        /// <summary>
        /// Deletes all entities.
        /// </summary>
        public void DeleteAllEntities()
        {
            Entities.ForEach(e => Delete(e));
        }


        /// <summary>
        /// Gets the entities of the table.
        /// </summary>
        /// <value>The entities.</value>
        public List<T> Entities
        {
            get { return _context.TableEntities.ToList(); }
        }

        /// <summary>
        /// Gets the context of the entities.
        /// </summary>
        /// <value>The context.</value>
        protected IDataServiceContext<T> Context
        {
            get
            {
                return _context;
            }
        }
    }
}
